#ifndef _ZERO_INCLUDE_LIB_H
#define _ZERO_INCLUDE_LIB_H
namespace zero
{
// stack <([{
/*
template<typename _Tp, typename _Sequence = deque<_Tp> >
class stack
{
public:
	typedef typename _Sequence::value_type                value_type;
	typedef typename _Sequence::reference                 reference;
	typedef typename _Sequence::const_reference           const_reference;
	typedef typename _Sequence::size_type                 size_type;
	typedef          _Sequence                            container_type;

protected:
	_Sequence c;

public:
	explicit stack(const _Sequence& __c = _Sequence()) : c(__c) { }

	bool empty() const { return c.empty(); }

	size_type size() const { return c.size(); }

	reference top() { __glibcxx_requires_nonempty(); return c.back(); }

	void push(const value_type& __x) { c.push_back(__x); }

	void pop() { __glibcxx_requires_nonempty(); c.pop_back(); }
};
*/
// }])>

// common C functions <([{
inline void assert(bool cond)
{
	while (!cond) {}
}

inline void memcpy(void* src, void* dest, long count)
{
	switch (count) {
		case 0:
			return;
		case 1:
			*(unsigned char *) dest = *(unsigned char *) src;
			return;
		case 2:
			*(unsigned short *) dest = *(unsigned short *) src;
			return;
		case 3:
			*(unsigned short *) dest = *(unsigned short *) src;
			*(2 + (unsigned char *) dest) = *(2 + (unsigned char *) src);
			return;
		case 4:
			*(unsigned long *) dest = *(unsigned long *) src;
			return;
	}
#define COMMON(x) \
asm volatile ( \
	"rep ; movsl" \
	x \
	: \
	: "c" (count / 4), "S" (src), "D" (dest) \
	: "memory")

	switch (count % 4) {
		case 0:
			COMMON("");
			return;
		case 1:
			COMMON("\n\tstosb");
			return;
		case 2:
			COMMON("\n\tstosw");
			return;
		default:
			COMMON("\n\tstosw\n\tstosb");
			return;
	}
#undef COMMON
}

inline bool bstrcmp(const char* src, int count, const char* dest)
{
	bool result = false;
	if (count >= 4) {
		asm (
			"repz; cmpsl; sete %0"
			: "=g" (result), "=S" (src), "=D" (dest)
			: "S" (src), "D" (dest), "c" (count/4)
			: );
		if (!result)
			return result;
		count &= 3;
	}
	switch (count) {
		case 0:
			result = true;
			break;
		case 1:
			result = *src == *dest;
			break;
		case 2:
			result = *(unsigned short *) src == *(unsigned short *) dest;
			break;
		case 3:
			result = *((unsigned short *) src) == *((unsigned short *) dest);
			if (!result)
				break;
			src += 2; dest += 2;
			result = *src == *dest;
			break;
	}
	return result;
}
// }])>
}
#endif
// vim: foldmarker=<([{,}])> foldmethod=marker
